package org.luxor.commons.zookeeper.component;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.luxor.commons.zookeeper.config.properties.ZookeeperProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Hashtable;
import java.util.List;
import java.util.Optional;

/**
 * 子节点监听器，可监听节点下一级子节点的增、删、改操作
 * @author Mr.Yan  @date: 2020/12/23
 */
public class PathChildrenCacheWatcher {
    private static final Logger logger = LoggerFactory.getLogger(PathChildrenCacheWatcher.class);

    private Hashtable<String, PathChildrenCache> pathChildrenCaches = new Hashtable<String, PathChildrenCache>();
    private CuratorFramework curatorFramework;
    private ZookeeperProperties zookeeperProperties;

    public PathChildrenCacheWatcher(CuratorFramework curatorFramework, ZookeeperProperties zookeeperProperties) {
        this.zookeeperProperties = zookeeperProperties;
        this.curatorFramework = curatorFramework;
    }
    /**
     * 添加 子节点监听器
     *
     * @param pathChildrenCacheListener 监听接收器
     */
    public void addWatcher(String path, PathChildrenCacheListener pathChildrenCacheListener) throws Exception {
        if (!StringUtils.hasText(path)) {
            return;
        }
        List<String> ignores = zookeeperProperties.getListenerIgnores();
        if (!CollectionUtils.isEmpty(ignores) && CollectionUtils.contains(ignores.iterator(), path)) {
            logger.warn("PathChildrenWatcher监听器:[ {} ] 注册，因白名单配置原因被忽略", pathChildrenCacheListener.getClass());
            return;
        }
        if (pathChildrenCaches.containsKey(path)) {
            logger.warn("PathChildrenWatcher监听器:[ {} ] 注册，因存在其它观察对象被忽略", pathChildrenCacheListener.getClass());
            return;
        }

        PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework, path, true);
        pathChildrenCache.getListenable().addListener(pathChildrenCacheListener);
        // 添加监听器记录
        pathChildrenCaches.put(path, pathChildrenCache);
        // 开启监听
        pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
    }

    /**
     * 获取 子节点监听器
     */
    public Optional<PathChildrenCache> getWatcher(String path) {
        if (StringUtils.hasText(path)) {
            return Optional.ofNullable(pathChildrenCaches.get(path));
        }
        return Optional.empty();
    }

    /**
     * 移除 子节点监听器
     */
    public void removeWatcher(String path) {
        try {
            if (StringUtils.hasText(path)) {
                pathChildrenCaches.remove(path).close();
            }
        } catch (Exception e) {
            // .ignore
        }
    }

}
